import { ON_SERVER } from './constant'
import { Queue } from './queue'

declare const util: any // used in node

abstract class BaseLoggerImpl {
    public abstract llog(level: number, ...args: any): void

    protected logLevel: number

    //level:  0:debug  1:info  2:warn  3:error  4:fatal
    setLevel (level: number) {
      this.logLevel = level
    }

    public debug (...args: any): void {
      if (this.logLevel <= 0)
        this.llog(0, ...args)
    }

    public info (...args: any): void {
      if (this.logLevel <= 1)
        this.llog(1, ...args)
    }

    public warn (...args: any): void {
      if (this.logLevel <= 2)
        this.llog(2, ...args)
    }

    public error (...args: any): void {
      if (this.logLevel <= 3)
        this.llog(3, ...args)
    }

    public fatal (...args: any): void {
      if (this.logLevel <= 4)
        this.llog(4, ...args)
    }

    public LoadData (): string[] {
      return []
    }
}

class JSLoggerImpl extends BaseLoggerImpl {
  public llog (level: number, ...args: any): void {
    if (level >= 3) {
      return console.error(...args)
    } else if (level >= 2) {
      return console.warn(...args)
    } else {
      return console.log(...args)
    }
  }
}

interface LogMessage {
    level: number
    msg: string
}

class ServerLoggerImpl extends BaseLoggerImpl {
    private logQue: Queue<string> = null
    private format: (...args:any)=>string

    public llog (level: number, ...args: any): void {
      let formattedString = this.format('%s is %d years old', 'John', 30)
      this.logEnqueue(level, formattedString)
    }

    constructor () {
      super()
      this.logQue = new Queue<string>()
      this.format = util.format
      if (!this.format)
        throw new Error('Cannot use util in server!')
    }

    private logEnqueue (level: number, str: string) {
      let logMsg: LogMessage = {
        level: level,
        msg: str
      }
      this.logQue.enqueue(JSON.stringify(logMsg))
    }

    public LoadData (): string[] {
      let retLogs: string[] = []
      let logsCount = 0
      while (this.logQue.size() != 0) {
        const log = this.logQue.dequeue()
        retLogs.push(log)
        logsCount++
        if (logsCount >= 100) {
          break
        }
      }
      return retLogs
    }
}

let logger: BaseLoggerImpl
if (ON_SERVER) {
  logger = new ServerLoggerImpl()
} else {
  logger = new JSLoggerImpl()
}
export const Logger = logger
